namespace EyeOpen.Testing
{
	using System;
	using System.Collections.Generic;
	using System.Linq;

	using EyeOpen.Data;
	using EyeOpen.Domain;

	using Moq;

	public class RepositoryMock<T>
		where T : class, IEntity
	{
		public RepositoryMock(params T[] collection)
		{
			Object = CreateMockRepository(collection);
		}

		public IRepository<T> Object { get; private set; }

		private IRepository<T> CreateMockRepository(params T[] collection)
		{
			var mockRepository = new Mock<IRepository<T>>();

			var list = new List<T>(collection);

			var queryable = list.AsQueryable();

			mockRepository.SetupGet(x => x.Provider).Returns(queryable.Provider);

			mockRepository.SetupGet(x => x.Expression).Returns(queryable.Expression);

			mockRepository.Setup(x => x.Add(It.IsAny<T>())).Callback<T>(list.Add);

			mockRepository.Setup(x => x.Remove(It.IsAny<T>())).Callback<T>(x => list.Remove(x)).Returns(true);

			mockRepository.Setup(x => x.Update(It.IsAny<T>())).Callback<T>(
				x =>
					{
						{
							var position = -1;

							for (var i = 0; i < list.Count; i++)
							{
								if (!list[i].Id.Equals(x.Id))
								{
									continue;
								}

								position = i;
								break;
							}

							if (position == -1)
							{
								throw new Exception("Object not found.");
							}

							list[position] = x;
						}
					});

			return mockRepository.Object;
		}
	}
}